#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/1/16 18:46
# @Author  : leon yan
# @Site    : 
# @File    : qpytableview.py
# @Software: PyCharm
import json
from enum import Enum  # 枚举类型

from PyQt5.QtCore import pyqtSlot, QItemSelectionModel, Qt
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QBrush, QColor
from PyQt5.QtWidgets import (QApplication, QWidget,
                             QAbstractItemView, QInputDialog, QMessageBox)

import Globalist as gl
import lib.qsqledit as sql
from UserEdit import QUserEdit
from lib.qsqledit import QSQL
from lib.qtabdelegates import EmptyDelegate, QmyComboBoxDelegate, QmyFloatSpinDelegate
from resource.qpytableview_ui import Ui_Form


class QTableHeader(Enum):
    """线上列表"""
    LineList = ["序号", 'Id', "工艺二维码", "工艺名名称", "存储时间", '状态', "操作者"]
    LineList_Width = [80, 150, 300, 280, 100, 90, 160]

    """用户管理页"""
    UserTable = ["Id", "用户姓名", "账号", "密码", "手机", "组别", "描述"]
    UserTable_Width = [90, 150, 150, 150, 150, 150, 300]

    """设备设定页"""
    DeviceParameter = ["Id", "参数号", "机器名", "设定值", "实际值", "描述"]
    DeviceParameter_Width = [90, 140, 140, 140, 140, 500]

    """设备信息页"""
    Device = ["序号", "编码", "名称", "Ip地址", "功率", "通电时间(h)", "运行时间(h)", "报警停机时间(h)", "报警发送次数", "在线", "描述"]
    Device_Width = [90, 150, 200, 160, 100, 140, 140, 160, 140, 60, 500]

    """设备设定页"""
    AlarmCode = ["故障代码", "描述", "等级"]
    AlarmCode_Width = [100, 800, 90]

    """PlcBit"""
    PlcBit = ["Var_type", "+0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9"]
    PlcBit_Width = [100, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90]

    """PlcWord"""
    PlcWord = ["Var_type", "+0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9"]
    PlcWord_Width = [100, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90]

    """PlcFloat"""
    PlcFloat = ["Var_type", "+0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9"]
    PlcFloat_Width = [100, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90]

    """sanderPlc"""
    sanderPlc = ["Var_type", "+0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9", "+10", "+11", "+12", "+13"]
    sanderPlc_Width = [100, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90]


class QPyTableView(QWidget, Ui_Form):
    def __init__(self, parent=None, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.setupUi(self)
        self.comboDelegate1 = QmyComboBoxDelegate(self)
        self.comboDelegate2 = QmyComboBoxDelegate(self)
        self.forceStatus = False
        self.forcesLock = False
        self.COL_COUNT = 0
        self.itemModel = QStandardItemModel(0, 0, self)  # 数据模型,1行3列
        self.selectionModel = QItemSelectionModel(self.itemModel)  # Item选择模型
        self.strTableName = None
        # 创建自定义代理组件并设置
        self.spinDevice = QmyFloatSpinDelegate(0, 20000, 0, self)  # 设备参数
        self.spinLength = QmyFloatSpinDelegate(0, 6000, 2, self)  # 未用
        self.spinDegree = QmyFloatSpinDelegate(1, 359, 1, self)  # 未用

    def setTableSheet(self, strTableName, developerMode=False):
        self.strTableName = strTableName
        headerList = QTableHeader[strTableName].value
        headerWidth = QTableHeader[strTableName + "_Width"].value
        if strTableName == "UserTable":
            '''设置不可编辑'''
            self.tableView.setItemDelegateForColumn(0, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(1, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(2, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(3, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(4, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(5, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(6, EmptyDelegate(self))
            '''
            '''
            if gl.get_value("Admin") == 1 or gl.get_value("Admin") == 2:
                bAdmin = True
            else:
                bAdmin = False
            if bAdmin:
                self.btnAddUser.setVisible(True)
                self.btnDel.setVisible(True)
                self.btnPswChange.setVisible(True)
                self.frame.setVisible(True)
            else:
                self.btnAddUser.setVisible(False)
                self.btnDel.setVisible(False)
                self.btnPswChange.setVisible(False)
                self.frame.setVisible(False)
            self.btnAdd.setVisible(False)
            self.btnInsert.setVisible(False)
            self.btnSave.setVisible(False)
            self.btnUpLoad.setVisible(False)
            self.btnDownLoad.setVisible(False)
        elif strTableName == "DeviceParameter":
            self.tableView.setItemDelegateForColumn(0, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(1, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(2, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(3, self.spinDevice)
            self.tableView.setItemDelegateForColumn(4, EmptyDelegate(self))
            self.tableView.setItemDelegateForColumn(5, EmptyDelegate(self))
            if developerMode:  # 后台模式
                self.btnAdd.setVisible(True)
                self.btnInsert.setVisible(True)
                self.btnDel.setVisible(True)
            else:
                self.btnAdd.setVisible(False)
                self.btnInsert.setVisible(False)
                self.btnDel.setVisible(False)
            self.btnAddUser.setVisible(False)
            self.btnPswChange.setVisible(False)
            self.frame.setVisible(True)
        elif strTableName == "Device":
            for i in range(5):
                self.tableView.setItemDelegateForColumn(i, EmptyDelegate(self))
        elif strTableName == "AlarmCode":
            for i in range(3):
                self.tableView.setItemDelegateForColumn(i, EmptyDelegate(self))
        elif strTableName == "PlcBit" or strTableName == "PlcWord" or strTableName == "PlcFloat":
            for i in range(11):
                self.tableView.setItemDelegateForColumn(i, EmptyDelegate(self))
        elif strTableName == "sanderPlc":
            for i in range(15):
                self.tableView.setItemDelegateForColumn(i, EmptyDelegate(self))
        elif strTableName == "LineList":
            for i in range(6):
                self.tableView.setItemDelegateForColumn(i, EmptyDelegate(self))
        else:
            return
        self.COL_COUNT = len(headerList)
        self.itemModel = QStandardItemModel(0, self.COL_COUNT, self)  # 数据模型,1行3列
        self.itemModel.setHorizontalHeaderLabels(headerList)  # 设置表头文字
        self.selectionModel = QItemSelectionModel(self.itemModel)  # Item选择模型
        self.selectionModel.currentChanged.connect(self.do_currentChanged)
        # self.tableView.doubleClicked.connect(self.edtRow)

        headColTab = self.tableView.horizontalHeader()
        headColTab.setStyleSheet("QHeaderView::section{background:#454545;color:#ffffff; font: 9pt 3ds;}")
        headRowTab = self.tableView.verticalHeader()
        headRowTab.setStyleSheet("QHeaderView::section{background:#454545;color:#ffffff}")

        # 为tableView设置数据模型
        self.tableView.setModel(self.itemModel)  # 设置数据模型
        self.tableView.setSelectionModel(self.selectionModel)  # 设置选择模型

        # oneOrMore = QAbstractItemView.ExtendedSelection
        # self.tableView.setSelectionMode(oneOrMore)  # 可多选

        if strTableName == "UserTable" or strTableName == "LineList" or strTableName == "aliTsl" or strTableName == "localTsl":
            itemOrRow = QAbstractItemView.SelectRows
            self.tableView.setSelectionBehavior(itemOrRow)  # 单元格选择
        else:
            itemOrRow = QAbstractItemView.SelectItems
            self.tableView.setSelectionBehavior(itemOrRow)  # 单元格选择

        self.tableView.verticalHeader().setDefaultSectionSize(22)  # 缺省行高
        self.tableView.setEnabled(True)  # tableView使能，默认是使能的
        self.tableView.horizontalHeader().resizeSection(0, headerWidth[0])  # 设置第1列的宽度
        self.tableView.horizontalHeader().resizeSection(1, headerWidth[1])  # 设置第2列的宽度
        if self.COL_COUNT > 2:
            self.tableView.horizontalHeader().resizeSection(2, headerWidth[2])  # 设置第3列的宽度
        if self.COL_COUNT > 3:
            self.tableView.horizontalHeader().resizeSection(3, headerWidth[3])  # 设置第4列的宽度
        if self.COL_COUNT > 4:
            self.tableView.horizontalHeader().resizeSection(4, headerWidth[4])  # 设置第5列的宽度
        if self.COL_COUNT > 5:
            self.tableView.horizontalHeader().resizeSection(5, headerWidth[5])  # 设置第6列的宽度
        if self.COL_COUNT > 6:
            self.tableView.horizontalHeader().resizeSection(6, headerWidth[6])  # 设置第6列的宽度
        if self.COL_COUNT > 7:
            self.tableView.horizontalHeader().resizeSection(7, headerWidth[7])  # 设置第6列的宽度
        if self.COL_COUNT > 8:
            self.tableView.horizontalHeader().resizeSection(8, headerWidth[8])  # 设置第6列的宽度
        if self.COL_COUNT > 9:
            self.tableView.horizontalHeader().resizeSection(9, headerWidth[9])  # 设置第6列的宽度
        if self.COL_COUNT > 10:
            self.tableView.horizontalHeader().resizeSection(10, headerWidth[10])  # 设置第6列的宽度
        if self.COL_COUNT > 11:
            self.tableView.horizontalHeader().resizeSection(11, headerWidth[11])  # 设置第6列的宽度
        if self.COL_COUNT > 12:
            self.tableView.horizontalHeader().resizeSection(12, headerWidth[12])  # 设置第6列的宽度
        if self.COL_COUNT > 13:
            self.tableView.horizontalHeader().resizeSection(13, headerWidth[13])  # 设置第6列的宽度
        if self.COL_COUNT > 14:
            self.tableView.horizontalHeader().resizeSection(14, headerWidth[14])  # 设置第6列的宽度
        if self.COL_COUNT > 15:
            self.tableView.horizontalHeader().resizeSection(15, headerWidth[15])  # 设置第6列的宽度

        '''生成表格'''
        self.fileToTable()

    def __del__(self):
        print("qpytableview is deleted")

    def fileToTable(self, strListData=None):
        if strListData:
            lst = strListData
        else:
            if self.strTableName == "UserTable":
                aFields = ['id', 'UserName', 'LoginId', 'Password', 'Phone', 'LevelType', 'Descriptions', 'Admin']
                strOrder = "order by id"
            elif self.strTableName == "DeviceParameter":
                aFields = ['id', 'ParameterNum', 'MachineType', 'DefaultValue', 'PlcValue', 'Descriptions']
                strOrder = "order by id"
            elif self.strTableName == "AlarmCode":
                aFields = ['AlarmCode', 'Descriptions', 'Grade']
                strOrder = "order by id"
            elif self.strTableName == "Device":
                aFields = ['Num', 'Code', 'Name', 'Ip', "Power", "PowerOn_time", "Running_time", "Alarm_stop_time", "Number_of_alarms", "Descriptions"]
                strOrder = "order by Num"
            else:
                return
            dictWhere = ""
            strOrder = "order by id"
            obj = QSQL(self.strTableName, dictWhere, strOrder, aFields)
            rdData = obj.showLst()
            lst = json.loads(rdData)

        if lst is None or lst == []:
            return
        else:
            for i in range(len(lst)):
                for j in range(self.COL_COUNT):
                    if len(lst[i]) > j:
                        if self.strTableName == "UserTable" and j == 3:
                            aa = "******"
                        elif self.strTableName == "Device" and j == 4:
                            if lst[i][j] is None:
                                aa = ""
                            else:
                                aa = str(lst[i][j])
                        else:
                            aa = str(lst[i][j])
                        item = QStandardItem(aa)
                        # 设置每个位置的文本值
                        self.itemModel.setItem(i, j, item)
                        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

    def do_Add(self):  # 在最后添加一行
        itemList = []  # 列表
        aa = self.itemModel.rowCount()
        for i in range(self.COL_COUNT):
            if i == 0:
                item = QStandardItem('-1')
            else:
                item = QStandardItem("")
            itemList.append(item)

        self.itemModel.appendRow(itemList)
        curIndex = self.itemModel.index(self.itemModel.rowCount() - 1, 0)
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)

    def do_Del(self):
        curIndex = self.selectionModel.currentIndex()  # 获取当前选择单元格的模型索引
        if curIndex.row() == -1:
            QMessageBox.information(self, "Tips", "No records selected to delete")
            return
        if self.itemModel.rowCount() == 1 and self.strTableName == "UserTable":
            QMessageBox.information(self, "Tips", "One user must be retained")
            return
        ret = QMessageBox.question(self, "Tips", "Are you sure you want to delete this record?")
        if ret != QMessageBox.Yes:
            return
        curIndex = self.selectionModel.currentIndex()  # 获取当前选择单元格的模型索引
        item = self.itemModel.item(curIndex.row(), 0)
        DbId = item.text()
        if gl.get_value("Admin") != 2:
            if self.strTableName == "UserTable":
                aa = sql.ReadDB(self.strTableName, int(DbId))
                if aa[0][7]:
                    QMessageBox.information(self, "Tips", "Administrator cannot be deleted")
                    return
        self.itemModel.removeRow(curIndex.row())  # //删除当前行
        '''并删除数据库'''
        sql.DeleteDbRecord(self.strTableName, DbId)

    def do_Insert(self):
        itemList = []  # 列表
        for i in range(self.Col_Count - 1):
            item = QStandardItem("0")
            itemList.append(item)

        curIndex = self.selectionModel.currentIndex()  # 获取当前选中项的模型索引
        self.itemModel.insertRow(curIndex.row(), itemList)  # 在当前行的前面插入一行
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)

    def do_Insert2(self, insertList):
        itemList = []  # 列表
        for i in range(7):
            item = QStandardItem(insertList[i])
            itemList.append(item)
        curIndex = self.selectionModel.currentIndex()  # 获取当前选中项的模型索引
        self.itemModel.insertRow(0, itemList)  # 在当前行的前面插入一行
        # self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)

    @pyqtSlot()
    def do_Update(self):
        Lst = []
        for i in range(self.itemModel.rowCount()):
            LstSub = []
            columnCount = self.itemModel.columnCount()
            for j in range(columnCount):
                item = self.itemModel.item(i, j)
                if item:
                    LstSub.append(str(item.text()))
                else:
                    LstSub.append("")
            Lst.append(LstSub)
        if not Lst:
            QMessageBox.warning(self, 'warning', 'The file is empty, saving failed!')
            return
        try:
            # 保存到数据库
            self.doSaveToDb(Lst)
        except [Exception] as e:
            print(e)

    def doSaveToDb(self, lst):
        ret = sql.SaveParameterDb(self.strTableName, lst)
        if ret:
            QMessageBox.information(self, "Tips", "Saved successfully!")
            return True
        else:
            QMessageBox.critical(self, "Error", "Save failed!")
            return False

    def do_AddUser(self):
        self._OpenUserEdit(None)

    def do_ChangePsw(self):
        curIndex = self.selectionModel.currentIndex()  # 获取当前选择单元格的模型索引
        if curIndex.row() == -1:
            QMessageBox.information(self, "Tips", "No record selected to modify")
            return
        curIndex = self.selectionModel.currentIndex()  # 获取当前选择单元格的模型索引
        item = self.itemModel.item(curIndex.row(), 0)
        DbId = int(item.text())
        self._OpenUserEdit(DbId)

    '''与PLC的交互'''

    def do_UpdateParameter(self):
        if gl.get_value("bEnablePlcWrite"):
            if not gl.get_value('bPlcWriting'):
                gl.set_value("bEnablePlcWrite", 0)
        else:
            # aa = self.itemModel.rowCount()
            if self.strTableName == "DeviceParameter":
                for i in range(100):
                    # print(i % 10, i//10)
                    aa = gl.get_value("parameter_plc_dict")
                    if aa[i//10]:
                        aa2 = aa[i//10][i % 10]
                    else:
                        aa2 = 0
                    item = QStandardItem(str(aa2))

                    # 设置每个位置的文本值
                    self.itemModel.setItem(i, 4, item)
                    item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                    item.setBackground(QBrush(QColor(88, 194, 38)))
            elif self.strTableName == "PlcBit":
                aa = gl.global_var["Plc_Interface"]["M600"]
                i = 0
                for key, value in aa.items():
                    item = QStandardItem("Plc_" + key + "M0")
                    self.itemModel.setItem(i, 0, item)
                    for j in range(10):
                        item = QStandardItem(str(aa[key][j]))
                        self.itemModel.setItem(i, j + 1, item)
                    i += 1
            elif self.strTableName == "PlcWord":
                aa = gl.global_var["Plc_Interface"]["Word"]
                i = 0
                for key, value in aa.items():
                    item = QStandardItem("Plc_" + key + "HD0")
                    self.itemModel.setItem(i, 0, item)
                    for j in range(10):
                        item = QStandardItem(str(aa[key][j]))
                        self.itemModel.setItem(i, j + 1, item)
                    i += 1
            elif self.strTableName == "PlcFloat":
                aa = gl.global_var["Plc_Interface"]["Float"]
                i = 0
                for key, value in aa.items():
                    item = QStandardItem("Plc_" + key + "D0")
                    self.itemModel.setItem(i, 0, item)
                    for j in range(10):
                        item = QStandardItem(str(aa[key][j]))
                        self.itemModel.setItem(i, j + 1, item)
                    i += 1
            elif self.strTableName == "sanderPlc":
                aa = gl.global_var["sander_1"]["readWord"]
                if aa:
                    item = QStandardItem("砂光机1")
                    self.itemModel.setItem(0, 0, item)
                    for j in range(14):
                        item = QStandardItem(str(aa[j]))
                        self.itemModel.setItem(0, j + 1, item)
                aa = gl.global_var["sander_2"]["readWord"]
                if aa:
                    item = QStandardItem("砂光机2")
                    self.itemModel.setItem(1, 0, item)
                    for j in range(14):
                        item = QStandardItem(str(aa[j]))
                        self.itemModel.setItem(1, j + 1, item)

    def do_UpLoad(self):
        r = QMessageBox.question(self, "Tips for uploading to PC", "Are you sure you want to upload the actual\n"
                                                                   " value of PLC to PC and save it?")
        if r != QMessageBox.Yes:
            return
        aa = self.itemModel.rowCount()
        if self.strTableName == "DeviceParameter":
            for i in range(aa):
                # 源
                item1 = self.itemModel.item(i, 4)
                # 目的
                item2 = QStandardItem(item1.text())
                self.itemModel.setItem(i, 3, item2)
                item2.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            # self.do_Update()

    def do_DownLoad(self):
        r = QMessageBox.question(self, "Download to PLC prompt", "Are you sure you want to download\n"
                                                                 " the settings to the PLC?")
        if r != QMessageBox.Yes:
            return
        gl.set_value("bEnablePlcWrite", 1)
        if self.strTableName == "DeviceParameter":
            lst = self.readListTable()
            ret = sql.SaveParameterDb(self.strTableName, lst)
            aa = sql.ReadDB2("DeviceParameter", 'ParameterNum')  # 按参数号排序
            if ret:
                tmpDict = {}
                for i in range(10):
                    tmpDict[i] = []  # 数据库用于写入PLC,初始化
                gl.set_value("parameter_dict", tmpDict)
                for i in range(len(aa)):
                    gl.Parameter2Var(aa[i][2], aa[i][3])
                # print(gl.get_value("parameter_dict"))
                # 设定10个PLC的写入标志
                for i in range(10):
                    gl.set_value("bPlcWriting_" + str(i), 1)

    def _OpenUserEdit(self, DbId):
        self.formDoc = QUserEdit(DbId)  # 必须传递self，否则无法显示
        self.formDoc.setAttribute(Qt.WA_DeleteOnClose)
        self.formDoc.setWindowFlag(Qt.Window, True)

        self.formDoc.setWindowModality(Qt.WindowModal)
        self.formDoc.setWindowFlag(Qt.CustomizeWindowHint, True)
        self.formDoc.setWindowFlag(Qt.WindowMinMaxButtonsHint, False)
        self.formDoc.setWindowFlag(Qt.WindowCloseButtonHint, True)
        self.formDoc.setWindowFlag(Qt.WindowStaysOnTopHint, True)

        self.formDoc.setWindowOpacity(1.0)  # 窗口透明度
        self.formDoc.show()
        self.formDoc.UserUpdate.connect(self.fileToTable)

    def do_currentChanged(self, current, previous):
        pass

    def do_inputIntValue(self, sValue, item):
        dlgTitle = "输入"
        txtLabel = "设置整数0~65535"
        defaultValue = int(sValue)
        minValue = 0
        maxValue = 65535
        stepValue = 1

        inputValue, OK = QInputDialog.getInt(self, dlgTitle, txtLabel,
                                             defaultValue, minValue, maxValue, stepValue)
        if OK:  # ok
            item.setText(str(inputValue))
        self.forcesLock = False

    def do_inputBitValue(self, sValue, item):
        if sValue == 'off':
            sValue2 = 0
        else:
            sValue2 = 1

        dlgTitle = "输入"
        txtLabel = "设置0或1"
        defaultValue = sValue2
        minValue = 0
        maxValue = 1
        stepValue = 1

        inputValue, OK = QInputDialog.getInt(self, dlgTitle, txtLabel,
                                             defaultValue, minValue, maxValue, stepValue)
        if OK:
            if inputValue == 0:
                item.setText('off')
            else:
                item.setText('on')
        self.forcesLock = False

    def do_Force(self, btn):
        if self.forceStatus:
            self.forceStatus = False
            btn.setText("强制关")
            btn.setStyleSheet("")
        else:
            self.forceStatus = True
            btn.setText("强制开")
            btn.setStyleSheet("background:#32680f;color:#ffffff")

    def readListTable(self):
        rowCount = self.itemModel.rowCount()
        colCount = self.COL_COUNT
        strTabList = []
        for i in range(rowCount):
            strRowList = []
            for j in range(colCount):
                cellItem = self.itemModel.item(i, j)
                strRowList.append(cellItem.text())
            strTabList.append(strRowList)
        return strTabList


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    windowObj = QPyTableView()

    windowObj.show()
    sys.exit(app.exec_())
